/*
 * @file     player_smart.h
 * @brief    This is a declaration of smart player.
 *
 * @author   Franco Riberi
 * @email    fgriberi AT gmail.com
 *
 *
 * @date March 09
 *
 * This file is part of board-games.
 *
 * board-games is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * board-games is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with board-games.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "tictactoe_proxy.h"

/** @brief Internal representation of the board game. */
static TTTBoard _internalBoard;

/** @Brief Global variables used for save the best row and collumn where the smart player will play */
static Coord _bestRow, _bestCol;

/** @Brief Constants declaration */
static const unsigned int NO_WINNER = 0;
static const int BEST_SCORE = -1;
static const int INITIAL_PLAYER = -1;
static const unsigned int INITIAL_DEPTH = 0;

/** @Brief Represents positions in the board */
static const unsigned int INITIAL_POSITION = 0u;
static const unsigned int FIRST_POSITION = 1u;
static const unsigned int SECOND_POSITION = 2u;

/** @brief Represents a index in the board */
typedef unsigned int BoardIndex;

/**
 * @brief Update internal board.
 *
 * @param board The global board game.
 * @param internalBoard The internal board game.
 */
inline void updateInternalBoard(const TTTBoard board, TTTBoard* internalBoard);

/**
 * @brief Checks by rows whether there is a winner.
 *
 * @param board The current board game
 * @return If a player has won per row is returned, otherwise return 0.
 */
int checkWinnerInRow(/*const*/ TTTBoard* board);

/**
 * @brief Checks by columns whether there is a winner.
 *
 * @param board The current board game
 * @return If a player has won per column is returned, otherwise return 0.
 */
int checkWinnerInCol(/*const*/ TTTBoard* board);

/**
 * @brief Checks by diagonals whether there is a winner.
 *
 * @param board The current board game
 * @return If a player has won per diagonal is returned, otherwise return 0.
 */
int checkWinnerInDiagonal(/*const*/ TTTBoard* board);

/**
 * @brief Determines whether there is a winner.
 *
 * @param board The internal boad.
 * @return If a player has won is returned, otherwise return 0.
 */
int checkWinner(/*const*/ TTTBoard* board);

/**
 * @brief Update current score
 *
 * @param currentScore The current score
 * @param bestScore    The temporal best score
 * @param depth        Level deep in the tree of game
 * @param row          The current row
 * @param col          The current column
 * @return The currentScore if is greater than the bestScore, otherwise old bestScore.
 */
int updateScore(int currentScore, int bestScore, const unsigned int depth, const BoardIndex row, const BoardIndex col);

/**
 * @brief Analyze a movement
 *
 * @param row          The current row
 * @param col          The current column
 * @param currentScore The current score
 * @param player       The current player
 * @param depth        The current level deep in the tree of game
 * @param bestScore    The best score so far
 * @return The best score found
 */
int analyzeMovement(const BoardIndex row, const BoardIndex col, int currentScore, const int player, const unsigned int depth, int bestScore);

/**
 * @brief Calculate the best move for the smart player
 *
 * @param changed
 * @param tempScore The temporal best score

 * @param depth  Level deep in the tree of game
 */
int calculateBestMove(int currentScore, int bestScore, const int player, const unsigned int depth);

/**
 * @brief  Method responsible to set the next move by analyzing the tree of possibilities
 *
 * Sets the bestRow and bestCol global variables
 * @param player The current player
 * @param depth  Level deep in the tree of game
 * @return The best score for the player
 */
int minmax(const int player, const unsigned int depth);

/**
 * @brief Initial player
 *
 * @param p Current player
 */
void init_player(__attribute__((unused)) enum PLAYERS p);

/**
 * @brief Method performing a move
 *
 * @param board  Current board game
 * @param row    To save the next row movement
 * @param col    To save the next column movement
 */
void play(const TTTBoard board, Coord* row, Coord* col);
